#include "PropertyGenerator.h"

#include "MetaGenerator.h"

#include "HeadFile.h"

CPropertyGenerator::CPropertyGenerator(CHeadFile *InContext)
{
    Context = InContext;
    Result = std::make_shared<CPropertyInfo>();
}

void CPropertyGenerator::Generate()
{
    //skip RPROPERTY
    {
        auto RPRopertyToken = Context->GetCurrentToken();
        if(RPRopertyToken->Type == ETokenType::RPROPERTY)
        {
            Context->GotoNextToken();
            Result->ErrorToken=RPRopertyToken;
        }
        else
        {
            Context->RaiseError(RPRopertyToken, U"expect 'RPRoperty'");
            return ;
        }

    }

    //read meta
    {
        auto MetaGenerator = std::make_shared<CMetaGenerator>(Context);
        MetaGenerator->Generate();
        Result->Meta = MetaGenerator->Result;
    }

    //make sure 'Name' and  'Getter' is Exist, try find 'Setter'
    {
        if(!Result->Meta.contains(u8"Name"))
        {
            Context->RaiseError(Result->ErrorToken, U"expect 'Name'");
            return ;
        }
        else
        {
            auto NameValue=Result->Meta[u8"Name"];
            if(!NameValue)
            {
                Context->RaiseError(Result->ErrorToken, U"expect a string value for 'Name' ");
                return ;
            }
            else
            {
                if(!std::holds_alternative<std::u8string>(*NameValue))
                {
                    Context->RaiseError(Result->ErrorToken, U"expect a string value for 'Name' ");
                    return ;
                }

                Result->Name = std::get<std::u8string>(*NameValue);
            }

        }
        


        if(!Result->Meta.contains(u8"Getter"))
        {
            Context->RaiseError(Result->ErrorToken, U"expect 'Getter'");
            return ;
        }
        else
        {
            auto GetterValue=Result->Meta[u8"Getter"];
            if(!GetterValue)
            {
                Context->RaiseError(Result->ErrorToken, U"expect a string value for 'Getter' ");
                return ;
            }
            else
            {
                if(!std::holds_alternative<std::u8string>(*GetterValue))
                {
                    Context->RaiseError(Result->ErrorToken, U"expect a string value for 'Getter' ");
                    return ;
                }

                Result->GetterFunctionName = std::get<std::u8string>(*GetterValue);
            }

        }

        if(Result->Meta.contains(u8"Setter"))
        {
            auto SetterValue=Result->Meta[u8"Setter"];
            if(!SetterValue)
            {
                Context->RaiseError(Result->ErrorToken, U"expect a string value for 'Setter' ");
                return ;
            }
            else
            {
                if(!std::holds_alternative<std::u8string>(*SetterValue))
                {
                    Context->RaiseError(Result->ErrorToken, U"expect a string value for 'Setter' ");
                    return ;
                }

                Result->SetterFunctionName = std::get<std::u8string>(*SetterValue);
            }

        }
    }
}
